package context

import (
	"context"
	"fmt"
	"sync"
	"time"
)

// 初始的例子
func worker_no_break() {
	var wg sync.WaitGroup
	for {
		fmt.Println("worker")
		time.Sleep(time.Second)
	}
	// 如何接收外部命令实现退出
	wg.Done()
}

func context_handle() {
	wg.Add(1)
	go worker_no_break()
	// 如何优雅的实现结束子goroutine
	wg.Wait()
	fmt.Println("over")
}

// 全局变量方式存在的问题：
// 1. 使用全局变量在跨包调用时不容易统一
// 2. 如果worker中再启动goroutine，就不太好控制了。

var wg sync.WaitGroup
var exit bool

func worker() {
	for {
		fmt.Println("worker")
		time.Sleep(time.Second)
		if exit {
			break
		}
	}
	wg.Done()
}

func context_handle_break() {
	wg.Add(1)
	go worker()
	time.Sleep(time.Second * 3) // sleep3秒以免程序过快退出
	exit = true                 // 修改全局变量实现子goroutine的退出
	wg.Wait()
	fmt.Println("over")
}

var wgc sync.WaitGroup

func worker_context(ctx context.Context) {
LOOP:
	for {
		fmt.Println("worker")
		time.Sleep(time.Second)
		select {
		case <-ctx.Done(): // 等待上级通知
			break LOOP
		default:
		}
	}
	wgc.Done()
}

func context_handle_by_Loop() {
	ctx, cancel := context.WithCancel(context.Background())
	wgc.Add(1)
	go worker_context(ctx)
	time.Sleep(time.Second * 3)
	cancel() // 通知子goroutine结束
	wgc.Wait()
	fmt.Println("over")
}
